package com.runa.rccprotocol.analysis;

import com.alibaba.fastjson.JSON;
import com.runa.monitor.comm.dto.newComm.AffiliatePanelVO;
import com.runa.monitor.comm.dto.newComm.HotMeterVO;
import com.runa.monitor.comm.dto.newComm.ValveVO;
import com.runa.monitor.comm.entity.CommMeter;
import com.runa.monitor.comm.entity.CommNetEquipment;
import com.runa.persistence.DateUtil;
import com.runa.persistence.RepositoryServicePersis;
import com.runa.persistence.config.CommConfig;
import com.runa.protocol.util.FaultUtil;
import com.runa.protocol.analysis.MetaBufferAnalysis;
import com.runa.protocol.enums.ByteOrder;
import com.runa.protocol.util.ByteUtil;
import com.runa.protocol.util.DigitalUtil;
import com.runa.protocol.util.UtilTime;
import com.runa.rccprotocol.dto.AffirmDeny;
import com.runa.rccprotocol.dto.equdata.TerminalCalendarClock;
import com.runa.rccprotocol.dto.runa.RunaConcenAffirmDeny;
import com.runa.rccprotocol.dto.runa.RunaConcenResponseData;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import static com.runa.rccprotocol.analysis.RunaEquDataAnalysis.heatMeterFaults;

/**
 * @author zhuj
 * 瑞纳计量设备解析器
 */
@Slf4j
public class RunaDeviceAnalysis extends MetaBufferAnalysis<byte[]> {

    private SimpleDateFormat sdfValve = new SimpleDateFormat("ssmmHHddMMyy");

    private String netEquNo;

    @Override
    public int fill(byte[] data, int size, String netEquNo) {
        this.responseData = null;//控制错误报文
        this.netEquNo = netEquNo;
        int begin = 0;
        while (data[begin] == (byte) 0xfe) begin++;
        if (data[begin] == 0x68) {
            int deviceType = data[begin + 1] & 0xff;
            switch (deviceType) {
                case 0x25:
                case 0x20:
                    heatMeterData(begin + 2, data);
                    break;
                case 0x41:
                    houseValveData41(begin + 2, data);
                    break;
                case 0x81:
                    houseValveData81(begin + 2, data);
                    break;
                case 0x71:
                    int dataType = data[begin + 9] & 0xff;
                    if (dataType == 0x81) {
                        RunaConcenResponseData responseData = new RunaConcenResponseData();
                        responseData.addRepData(loraBuildValveData(begin + 2, data));
                        this.responseData = responseData;
                    } else if (dataType == 0x95) {
                        this.responseData = new RunaConcenAffirmDeny(true);
                    } else {
                        this.responseData = new RunaConcenAffirmDeny(false);
                    }
                    break;
            }
        } else if (data[begin] == 0x69 && data[begin+7] == 0x16) {
            RunaConcenAffirmDeny affirmDeny = new RunaConcenAffirmDeny(true);
            affirmDeny.setAddress(netEquNo);
            this.responseData = affirmDeny;
        } else if (data[begin + 1] == 3 && data[begin + 2] == 70) {
            RunaConcenResponseData responseData = new RunaConcenResponseData();
            responseData.setAddress(netEquNo);
            responseData.addRepData(buildValveData(data));
            this.responseData = responseData;
        } else if (data[begin + 1] == 16 && DigitalUtil.calcCrc16(data, 6) == ByteUtil.byteToUShort(data, 6, ByteOrder.BA)) {
            RunaConcenAffirmDeny affirmDeny = new RunaConcenAffirmDeny(true);
            affirmDeny.setAddress(netEquNo);
            this.responseData = affirmDeny;
        } else {
            RunaConcenAffirmDeny affirmDeny = new RunaConcenAffirmDeny(false);
            affirmDeny.setAddress(netEquNo);
            this.responseData = affirmDeny;
        }
        return 0;
    }


    public static void main(String[] args) {
        String s = "FEFEFE 68 20 75 36 49 59 00 11 11 81 2E 1F 90 12FE FEFEFEFE00 45 03 0005750400 00 17109300 003582 0771002C04510061460090 83 0220 13 01 08 09 212004 08DB 16";
        byte[] data = ByteUtil.hexStringToByte(s);

        int len = ByteUtil.byteToUShort(data, 1, ByteOrder.BA);
        RunaDeviceAnalysis runaDeviceAnalysis = new RunaDeviceAnalysis();

        runaDeviceAnalysis.fill(data, data.length, null);
        System.out.println(JSON.toJSONString(runaDeviceAnalysis.gain()));
        System.out.println("len: " + len);
        int length = data.length;
        System.out.println("length: " + length);
        int index = 18;
        while (data[index] == (byte) 0xfe) {

            index++;
        }
        if (data[index] == (byte)0x68) {
            if (data[index+1] == (byte) 0x25 || data[index+1] == (byte) 0x20) {
                log.debug("正定188: {} {}", "", ByteUtil.byteToHexString(data, 0, length));
                RunaConcenResponseData responseData = new RunaConcenResponseData();
                byte check = data[length - 2];
                if (check != ByteUtil.sum(data, 6, length - 8)) {
                    log.debug("校验和比较失败: {} {}", check, ByteUtil.sum(data, 6, length - 8));
                    return;
                }
                HotMeterVO hotMeterVO = runaDeviceAnalysis.heatMeterData(index + 2, data, false, true);
                System.out.println(JSON.toJSONString(hotMeterVO));
            }

        }

    }


    public HotMeterVO heatMeterData(String netSerialNo, byte[] bytes, int idx) {
        if ("正定".equals(CommConfig.getProjectAddress())) {
            String serialNo = ByteUtil.byteToHexStringFlip(bytes, idx, 4);
            CommMeter commMeter = RepositoryServicePersis.getByNetSerialAndSerialLeftLike(netSerialNo, serialNo);
            boolean dataOrder = false;
            if (null == commMeter) {
                log.debug("{} {} 未找到", netSerialNo, serialNo);
                serialNo = ByteUtil.byteToHexString(bytes, idx+3, 4);
                commMeter = RepositoryServicePersis.getByNetSerialAndSerialLeftLike(netSerialNo, serialNo);
                if (null != commMeter) {
                    dataOrder = true;
                }
            }
            log.debug("commMeter: {} {} {}", netSerialNo, serialNo, JSON.toJSONString(commMeter));
            boolean unitOrder = false;
            if (null != commMeter) {
                if (commMeter.getModel().endsWith("-U-FRONT")) {
                    unitOrder = true;
                }
                HotMeterVO hotMeterVO = heatMeterData(idx, bytes, unitOrder, dataOrder);
                hotMeterVO.setMeterSerial(commMeter.getSerial());
                return hotMeterVO;
            }
        }
        return heatMeterData(idx, bytes);
    }


    private String byteToHexString(byte[] b, int offset, int length, boolean order) {
        if (order) {
            return ByteUtil.byteToHexString(b, offset, length);
        }
        return ByteUtil.byteToHexStringFlip(b, offset, length);
    }

    public HotMeterVO heatMeterData(int idx, byte[] bytes, boolean unitOrder, boolean dataOrder) {
        RunaConcenResponseData responseData = new RunaConcenResponseData();
        HotMeterVO meter = new HotMeterVO();
        idx += 7;
        int ctrl = bytes[idx++] & 0xff;
        int len = bytes[idx++] & 0xff;
        String functionCode = ByteUtil.byteToHexStringFlip(bytes, idx, 3);
        idx += 3;
        boolean tianJinWanHua = functionCode.equals("0052C3");
        if (ctrl == 0x81 || (ctrl == 0xC1 && tianJinWanHua)) {
            //天津万华
            if (tianJinWanHua) {
                parseTianJinWanHua(idx, bytes, len, meter);
                //                parseTianJinWanHua(idx, bytes,meter);
            }
            if (unitOrder) {
                //todo 厂家编码
                int unit = bytes[idx++] & 0xff;
                float accCold = (float) (Integer.parseInt(byteToHexString(bytes, idx, 4, dataOrder)) * 0.01);
                idx += 4;

                unit = bytes[idx++] & 0xff;
                float accHeat = (float) (Integer.parseInt(byteToHexString(bytes, idx, 4, dataOrder)) * 0.01);
                idx += 4;
                meter.setAccHeat(toKwh(accHeat, unit));

                unit = bytes[idx++] & 0xff;
                float power = (float) (Integer.parseInt(byteToHexString(bytes, idx, 4, dataOrder)) * 0.01);
                idx += 4;
                meter.setPower(toKw(power, unit));

                unit = bytes[idx++] & 0xff;
                float flow = (float) (Integer.parseInt(byteToHexString(bytes, idx, 4, dataOrder)) * 0.0001);
                idx += 4;
                meter.setFlow(toM3h(flow, unit));

                unit = bytes[idx++] & 0xff;
                float accFlow = (float) (Integer.parseInt(byteToHexString(bytes, idx, 4, dataOrder)) * 0.01);
                idx += 4;
                meter.setAccFlow(toM3(accFlow, unit));

            } else {
                //todo 厂家编码
                float accCold = (float) (Integer.parseInt(byteToHexString(bytes, idx, 4, dataOrder)) * 0.01);
                idx += 4;
                idx++;
//            meter.setSettDateHeatColdVal(toKwh(accCold, bytes[idx++] & 0xff));
                float accHeat = (float) (Integer.parseInt(byteToHexString(bytes, idx, 4, dataOrder)) * 0.01);
                idx += 4;
                meter.setAccHeat(toKwh(accHeat, bytes[idx++] & 0xff));
                float power = (float) (Integer.parseInt(byteToHexString(bytes, idx, 4, dataOrder)) * 0.01);
                idx += 4;
                meter.setPower(toKw(power, bytes[idx++] & 0xff));
                float flow = (float) (Integer.parseInt(byteToHexString(bytes, idx, 4, dataOrder)) * 0.0001);
                idx += 4;
                meter.setFlow(toM3h(flow, bytes[idx++] & 0xff));
                float accFlow = (float) (Integer.parseInt(byteToHexString(bytes, idx, 4, dataOrder)) * 0.01);
                idx += 4;
                meter.setAccFlow(toM3(accFlow, bytes[idx++]));
            }

            meter.setSupplyTemp((float) (Integer.parseInt(byteToHexString(bytes, idx, 3, dataOrder)) * 0.01));
            idx += 3;
            meter.setReturnTemp((float) (Integer.parseInt(byteToHexString(bytes, idx, 3, dataOrder)) * 0.01));
            idx += 3;
            meter.setWorkTime(Integer.parseInt(byteToHexString(bytes, idx, 3, dataOrder)));
            idx += 3;
            if (dataOrder) {
                meter.setMeterDate(DateUtil.noLineFormatToDate(ByteUtil.byteToHexString(bytes, idx, 7)));
            } else {
                meter.setMeterDate(DateUtil.noLineFormatToDate(ByteUtil.byteToHexStringFlip(bytes, idx, 7)));
            }

            idx += 7;
            meter.setStatus(ByteUtil.byteToHexString(bytes, idx, 2));
            if ("FFFF".equals(meter.getStatus())) {
                meter.setSuccess(false);
            } else {
                meter.setFaultCode(heatMeterFaults(meter.getStatus()));
            }
            meter.setReadDate(new Date());
            responseData.addRepData(meter);
            this.responseData = responseData;
        } else {
            this.responseData = new RunaConcenAffirmDeny(false);
        }
        return meter;
    }


    public HotMeterVO heatMeterData(int idx, byte[] bytes) {
        RunaConcenResponseData responseData = new RunaConcenResponseData();
        HotMeterVO meter = new HotMeterVO();
//        HeatMeterData meter = new HeatMeterData();
        String addr = ByteUtil.byteToHexStringFlip(bytes, idx, 4);
        meter.setMeterSerial(addr);
//        hotMeter.set(addr);
        idx += 7;
        int ctrl = bytes[idx++] & 0xff;
        int len = bytes[idx++] & 0xff;
        String functionCode = ByteUtil.byteToHexStringFlip(bytes, idx, 3);
        idx += 3;
        boolean tianJinWanHua = functionCode.equals("0052C3");
        if (ctrl == 0x81 || (ctrl == 0xC1 && tianJinWanHua)) {
            //天津万华
            if (tianJinWanHua) {
                parseTianJinWanHua(idx, bytes, len, meter);
                //                parseTianJinWanHua(idx, bytes,meter);
            }
            //todo 厂家编码
            //冷量暂无
//            float accCold = (float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 4)) * 0.01);
            idx += 4;
            idx++;
//            meter.setSettDateHeatColdVal(toKwh(accCold, bytes[idx++] & 0xff));
            float accHeat = (float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 4)) * 0.01);
            idx += 4;
            meter.setAccHeat(toKwh(accHeat, bytes[idx++] & 0xff));
            float power = (float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 4)) * 0.01);
            idx += 4;
            meter.setPower(toKw(power, bytes[idx++] & 0xff));
            float flow = (float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 4)) * 0.0001);
            idx += 4;
            meter.setFlow(toM3h(flow, bytes[idx++] & 0xff));
            float accFlow = (float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 4)) * 0.01);
            idx += 4;
            meter.setAccFlow(toM3(accFlow, bytes[idx++]));
            meter.setSupplyTemp((float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 3)) * 0.01));
            idx += 3;
            meter.setReturnTemp((float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 3)) * 0.01));
            idx += 3;
            meter.setWorkTime(Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 3)));
            idx += 3;
            meter.setMeterDate(TerminalCalendarClock.getInstance(bytes, idx).toDate());
            idx += 7;
            meter.setStatus(ByteUtil.byteToHexString(bytes, idx, 2));
            if ("FFFF".equals(meter.getStatus())) {
                meter.setSuccess(false);
            } else {
                meter.setFaultCode(heatMeterFaults(meter.getStatus()));
            }
            meter.setReadDate(new Date());
            responseData.addRepData(meter);
            this.responseData = responseData;
        } else {
            this.responseData = new RunaConcenAffirmDeny(false);
        }
        return meter;
    }


    private void parseTianJinWanHua(int idx, byte[] bytes, int size, HotMeterVO meter) {
        int index = idx;
        for (; index < size + idx - 1; index++) {
            bytes[index] = (byte) ((bytes[index] & 0xff) - 0x33);
        }
        byte unit = bytes[idx++];
        float accCold = (float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 4)) * 0.01);
        idx += 4;
//        meter.setSettDateHeatColdVal(toKwh(accCold, unit & 0xff));
        unit = bytes[idx++];
        float accHeat = (float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 4)) * 0.01);
        idx += 4;
        meter.setAccHeat(toKwh(accHeat, unit & 0xff));
        unit = bytes[idx++];
        float power = (float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 4)) * 0.01);
        idx += 4;
        meter.setPower(toKw(power, unit & 0xff));
        unit = bytes[idx++];
        float flow = (float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 4)) * 0.0001);
        idx += 4;
        meter.setFlow(toM3h(flow, unit & 0xff));
        unit = bytes[idx++];
        float accFlow = (float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 4)) * 0.01);
        idx += 4;
        meter.setAccFlow(toM3(accFlow, unit));
        meter.setSupplyTemp((float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 3)) * 0.01));
        idx += 3;
        meter.setReturnTemp((float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 3)) * 0.01));
        idx += 3;
        meter.setWorkTime(Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 3)));
        idx += 3;
        meter.setMeterDate(TerminalCalendarClock.getInstance(bytes, idx).toDate());
        idx += 7;
        meter.setStatus(ByteUtil.byteToHexString(bytes, idx, 2));
        if ("FFFF".equals(meter.getStatus())) {
            meter.setSuccess(false);
        } else {
            meter.setFaultCode(heatMeterFaults(meter.getStatus()));
        }
        meter.setReadDate(new Date());

    }

    private void houseValveData41(int idx, byte[] bytes) {
        RunaConcenResponseData responseData = new RunaConcenResponseData();
        ValveVO valveVO = new ValveVO();
        String addr = ByteUtil.byteToHexStringFlip(bytes, idx, 4);
        valveVO.setValveSerial(addr);
        idx += 7;
        int ctrl = bytes[idx++] & 0xff;
        int len = bytes[idx++] & 0xff;
        if (ctrl == 0x81) {
            idx += 3;
            valveVO.setOpenLock(bytes[idx++] == (byte) 0xff);
            valveVO.setEnvTemp((float) (ByteUtil.bcdToInt(bytes, idx, 2, false) * 0.01));
            idx += 2;
            //todo 设定温度
            idx += 2;
            valveVO.setActOpen((float) bytes[idx++]);
            idx += 4;
            valveVO.setValveDate(UtilTime.StringToDate(ByteUtil.byteToHexStringFlip(bytes, idx, 7), "yyyyMMddHHmmss"));
            idx += 7;
            valveVO.setStatus(ByteUtil.byteToHexString(bytes, idx, 1));
            responseData.addRepData(valveVO);
            this.responseData = responseData;
        } else if (ctrl == 0x84) {
            idx += 3;
            this.responseData = new RunaConcenAffirmDeny(bytes[idx] == 1);
        }
    }

    private void houseValveData81(int idx, byte[] bytes) {
        RunaConcenResponseData responseData = new RunaConcenResponseData();
        ValveVO valveVO = new ValveVO();
//        ValveData valveData = new ValveData();
        String addr = ByteUtil.byteToHexStringFlip(bytes, idx, 4);
        valveVO.setValveSerial(addr);
        idx += 7;
        int ctrl = bytes[idx++] & 0xff;
        int len = bytes[idx++] & 0xff;
        if (ctrl == 0x81) {
            idx += 3;
            idx += 6;
            idx += 4;
            valveVO.setReadTime(new Date());
//            valveData.setAccHeat((float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 6)) * 0.01));
            idx += 6;
            valveVO.setOpenTime(Float.valueOf(ByteUtil.byteToInt(bytes, idx, ByteOrder.DCBA)));
            idx += 14;
            valveVO.setOpenLock(bytes[idx++] == 1);
//            idx++;
            valveVO.setRemoteSet((float) (bytes[idx++] & 0xff));
            idx++;
//            idx++;
            valveVO.setTempLock(bytes[idx++] == 1);
//            valveData.setTemperatureLockTarget((float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 2)) * 0.01));
            idx += 2;
            valveVO.setTempDL((float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 2)) * 0.01));
            idx += 2;
            valveVO.setTempUL((float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 2)) * 0.01));
            idx += 18;
            valveVO.setReturnTemp((float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 2)) * 0.01));
            idx += 2;
            valveVO.setSupplyTemp((float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 2)) * 0.01));
            idx += 2;
            try {
                valveVO.setValveDate(sdfValve.parse(ByteUtil.byteToHexString(bytes, idx, 6)));
            } catch (ParseException e) {
                
            }
            idx += 7;
            valveVO.setStatus(ByteUtil.byteToHexString(bytes, idx, 2));
            idx += 2;
            valveVO.setActOpen((float) bytes[idx++]);
            idx += 12;
//            valveData.setCurrTemperature((float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 2)) * 0.01));
            int vsn = bytes[idx] & 0x0f;
            idx += 2;
            float pt = (float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 2)) * 0.01);
            idx += 2;
            float ptSet = (float) (Integer.parseInt(ByteUtil.byteToHexStringFlip(bytes, idx, 2)) * 0.01);
            idx += 2;
            int counter = bytes[idx] & 0x0f;
            int voltage = (bytes[idx++] >> 4) & 0x0f;
            if ("FFFF".equals(valveVO.getStatus())) {
                valveVO.setSuccess(false);
            } else {
                valveVO.setFaultCode(FaultUtil.runaEquValveStatusFaults(valveVO.getStatus()));
            }
            AffiliatePanelVO panel = new AffiliatePanelVO(counter, vsn, pt, (short) (bytes[idx] & 0xff));
            panel.setSerial(valveVO.getValveSerial());
            panel.setReadTime(valveVO.getReadTime());
            //温度带面板使用map
//            HashMap<String, Object> stringObjectHashMap = new HashMap<>();
//            stringObjectHashMap.put("valve",valveVO);
//            stringObjectHashMap.put("panel",panel);
            responseData.addRepData(valveVO);
            this.responseData = responseData;
        } else if (ctrl == 0x84) {
            this.responseData = new RunaConcenAffirmDeny(true);
        } else {
            this.responseData = new RunaConcenAffirmDeny(false);
        }
    }

    private ValveVO loraBuildValveData(int idx, byte[] bytes) {
        ValveVO valve = new ValveVO();
        String addr = ByteUtil.byteToHexStringFlip(bytes, idx, 4);
        valve.setValveSerial(addr);
        idx += 7;
        int ctrl = bytes[idx++] & 0xff;
        int len = bytes[idx++] & 0xff;
        idx += 3;
        if (ctrl == 0x81) {
            idx += 4;
            int setOpen = ByteUtil.byteToUShort(bytes, idx, ByteOrder.AB);
            idx += 2;
            int open = ByteUtil.byteToUShort(bytes, idx, ByteOrder.AB);
//            int unit = open - open / 10 * 10;
//            int tens = (open - unit) / 10;
//            valve.setCurrOpenValve(((unit >= 5 ? (tens + 1) * 10 : (tens - 1) * 10) / 10));
            BigDecimal multiply = new BigDecimal(0.1);
            valve.setActOpen(new BigDecimal(open).multiply(multiply).setScale(0, RoundingMode.HALF_UP).floatValue());
            idx += 2;
            int param = ByteUtil.byteToUShort(bytes, idx, ByteOrder.AB);
            idx += 2;
            if ((param & 1) == 1) {
                valve.setRemoteSet(new BigDecimal(setOpen).multiply(multiply).setScale(0, RoundingMode.HALF_UP).floatValue());
            } else {
                valve.setRemoteSet((float) setOpen);
            }
            int version = ByteUtil.byteToUShort(bytes, idx, ByteOrder.AB);
            valve.setSoftVersion(String.valueOf(version));
            idx += 2;
            valve.setSupplyTemp((float) (ByteUtil.byteToUShort(bytes, idx, ByteOrder.AB) * 0.1));
            idx += 2;
            valve.setReturnTemp((float) (ByteUtil.byteToUShort(bytes, idx, ByteOrder.AB) * 0.1));
            idx += 2;
            valve.setSupplyPre((float) (ByteUtil.byteToUShort(bytes, idx, ByteOrder.AB) * 0.001));
            idx += 2;
            valve.setReturnPre((float) (ByteUtil.byteToUShort(bytes, idx, ByteOrder.AB) * 0.001));
            idx += 2;
            valve.setStatus(ByteUtil.byteToHexString(bytes, idx, 2));
            valve.setFaultCode(FaultUtil.runaDeviceBuildValveFaults(ByteUtil.byteToUShort(bytes, idx, ByteOrder.AB)));
            idx += 2;
            valve.setLR(ByteUtil.byteToUShort(bytes, idx, ByteOrder.AB) == 1 ? ValveVO.LREnum.远程 : ValveVO.LREnum.本地);
            idx += 2;
            valve.setModel(ValveVO.geneModel(ByteUtil.byteToUShort(bytes, idx, ByteOrder.AB)));
            idx += 2;
            try {
                valve.setValveDate(sdfValve.parse(ByteUtil.byteToHexString(bytes, idx, 6)));
            } catch (ParseException e) {
                
            }
            idx += 10;
            valve.setBatteryVol((float) (ByteUtil.byteToUShort(bytes, idx, ByteOrder.AB) * 0.001));
            idx += 10;
            valve.setOpenTime(Float.valueOf(ByteUtil.byteToInt(bytes, idx, ByteOrder.ABCD)));
            valve.setReadTime(new Date());
//            valve.setValveComm(true);
            return valve;
        }
        valve.setSuccess(false);
        return valve;
    }

    public ValveVO buildValveData(byte[] data) {
        ValveVO valveData = new ValveVO();
        valveData.setReadTime(new Date());
        valveData.setIndex(data[0] & 0xff);
        valveData.setRemoteSet((float) ByteUtil.byteToShort(data, 3, ByteOrder.AB));
        valveData.setActOpen((float) ByteUtil.byteToShort(data, 7, ByteOrder.AB));
        valveData.setSoftVersion(String.valueOf(ByteUtil.byteToShort(data, 17, ByteOrder.AB)));
        valveData.setSupplyTemp(ByteUtil.byteToFloat(data, 21, ByteOrder.CDAB));
        valveData.setReturnTemp(ByteUtil.byteToFloat(data, 25, ByteOrder.CDAB));
        valveData.setEnvTemp(ByteUtil.byteToFloat(data, 29, ByteOrder.CDAB));
        valveData.setSupplyPre(ByteUtil.byteToFloat(data, 33, ByteOrder.CDAB) / 1000);
        valveData.setBehindPre(ByteUtil.byteToFloat(data, 37, ByteOrder.CDAB) / 1000);
        valveData.setFrontPre(ByteUtil.byteToFloat(data, 41, ByteOrder.CDAB) / 1000);
        int statusCode = ByteUtil.byteToShort(data, 65, ByteOrder.AB) & 0xffff;
        valveData.setLR(ByteUtil.byteToShort(data, 67, ByteOrder.AB) == 1 ? ValveVO.LREnum.远程 : ValveVO.LREnum.本地);
        int model = ByteUtil.byteToShort(data, 69, ByteOrder.AB);
        switch (model) {
            case 1:
                valveData.setModel(ValveVO.ModelEnum.开度);
                break;
            case 2:
                valveData.setModel(ValveVO.ModelEnum.室温);
                break;
            case 3:
                valveData.setModel(ValveVO.ModelEnum.流速);
                break;
            case 4:
                valveData.setModel(ValveVO.ModelEnum.供回温差);
                break;
            case 5:
                valveData.setModel(ValveVO.ModelEnum.回温);
                break;
            case 6:
                valveData.setModel(ValveVO.ModelEnum.供温);
                break;
        }
        valveData.setStatus(Integer.toHexString(statusCode));
        ArrayList<String> list = new ArrayList<>();
        if ((statusCode >> 8 & 1) == 1) {
            list.add("进水故障");
        }
        if ((statusCode >> 9 & 1) == 1) {
            list.add("回水故障");
        }
        valveData.setFaultCode(list);
        return valveData;
    }

    public static float toKwh(float src, int unit) {
        switch (unit) {
            case 0x02:
                return src / 1000;
            case 0x08:
                return src * 1000;
            case 0x0a:
                return  src * 1000 * 100;
            case 0x01:
                return (float) (src / 1000000000 * 277.8);
            case 0x0b:
                return (float) (src / 1000000 * 277.8);
            case 0x0e:
                return (float) (src / 1000 * 277.8);
            case 0x11:
                return (float) (src * 277.8);
            case 0x13:
                return (float) (src * 100 * 277.8);
            default:
        }
        return src;
    }

    public static float toKw(float src, int unit) {
        switch (unit) {
            case 0x14:
                return src / 1000;
            case 0x1a:
                return src * 1000;
            default:
        }
        return src;
    }

    public static float toM3(float src, int unit) {
        if (unit == 0x29) {
            return src / 1000;
        }
        return src;
    }

    public static float toM3h(float src, int unit) {
        if (unit == 0x32) {
            return src / 1000;
        }
        return src;
    }




}
